package scu.maqiang.machinelearning;

import scu.maqiang.numeric.Algorithms;
import scu.maqiang.numeric.MVO;
import scu.maqiang.numeric.ParamCheck;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * KNN算法分类器类
 */
public class KNNClassifier {
    /**
     *
     * @param k
     */
    public KNNClassifier(int k) {
        assert (k > 0): "the value k must positive";
        this.k = k;
        x_train = null;
        y_train = null;
    }


    public void fit(double[][] x_train, int[] y_train) {
        ParamCheck.checkEqual(x_train.length, y_train.length);
        this.x_train = x_train;
        this.y_train = y_train;
    }

    public int predict(double[] x) {
        ParamCheck.checkEqual(x_train[0].length, x.length);
        double[] distance = new double[x_train[0].length];
        Arrays.setAll(distance, i -> MVO.distance(x_train[i], x));
        int[] permutationIdx = new int[distance.length];
        Algorithms.selectionSort(distance, permutationIdx, true);
        int[] kNeighbors = new int[k];
        Arrays.setAll(kNeighbors, i-> y_train[permutationIdx[i]]);
        Map<Integer, Long> map = IntStream.of(kNeighbors).boxed().collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
        //System.out.println("数字出现次数统计（数字=次数）：" + map);
        Optional<Integer> maxOptional = map.entrySet().stream().max(Comparator.comparing(Map.Entry::getValue)).map(Map.Entry::getKey);
        //System.out.println("出现次数最多的数字：" + maxOptional.get());
        return maxOptional.get();
    }

    public int[] predict(double[][] x_test) {
        int textLength = x_test.length;
        int[] result = new int[x_test.length];
        Arrays.setAll(result, i -> predict(x_test[i]));
        return result;
    }



    private int k;
    double[][] x_train;
    int[] y_train;

    public static void main(String[] args) {
        String fileName = "irisDataSet.txt";

    }
}
